package com.zhuqi.dynamic.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.zhuqi.dynamic.SignTools;
import com.zhuqi.dynamic.SymmetricEncoder;
import com.zhuqi.dynamic.domain.*;
import com.zhuqi.dynamic.ds1.mapper.Ds1Mapper;
import com.zhuqi.dynamic.ds2.mapper.Ds2Mapper;
import com.zhuqi.dynamic.ds3.mapper.Ds3Mapper;
import com.zhuqi.dynamic.service.SyncDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author : ZhuQi
 * @version : 时间:2022/5/6 14:07 版本:
 */
@Service
@Slf4j
public class SyncDataServiceImpl implements SyncDataService {

    @Autowired
    private Ds1Mapper ds1Mapper;

    @Autowired
    private Ds2Mapper ds2Mapper;

    @Autowired
    private Ds3Mapper ds3Mapper;

    /**
     * 数据存储的集合
     */
    private static ArrayList<UserDao> dataList = new ArrayList<>();

    /**
     * 餐补ID集合
     */
    private static List<Integer> ids = new ArrayList<>();


    @Override
    public void getDataToMemory() {
        log.info("进入数据加载方法");
        dataList = ds1Mapper.selectData();
        log.info("数据大小为 {}", dataList.size());
    }

    @Override
    public void syncData() {
        log.info("进入数据导入");
        ArrayList<UserDao> succList = new ArrayList<>();
        ArrayList<UserDao> errorList = new ArrayList<>();
        for (UserDao userDao : dataList) {
            String phoneNumber = userDao.getPhoneNumber();
            int i = ds2Mapper.selectUser(phoneNumber);
            if (i > 0) {
                succList.add(userDao);
            } else {
                errorList.add(userDao);
            }
        }
        ds2Mapper.batchUpdateUser(succList);
        log.info("错误数据 + ", errorList.toString());
        ArrayList<UserChargeDao> userChargeDaos = new ArrayList<>();
        for (UserDao userDao : errorList) {
            UserChargeDao userChargeDao = new UserChargeDao();
            userChargeDao.setPhonenumber(userDao.getPhoneNumber());
            userChargeDao.setUserName(userDao.getUserName());
            userChargeDaos.add(userChargeDao);
        }
        String filename = "./error.xlsx";
        EasyExcel.write(filename, UserChargeDao.class).sheet("1").doWrite(userChargeDaos);
    }

    @Override
    public void excel() {
        ArrayList<UserChargeDao> userChargeDaos = new ArrayList<>();

        userChargeDaos = ds1Mapper.selectChargeData();

        String filename = "./111.xlsx";
        EasyExcel.write(filename, UserChargeDao.class).sheet("1").doWrite(userChargeDaos);
    }

    /**
     * 订单同步
     */
    @Override
    public void orderSync() {
        ArrayList<OrderSuppDao> list = new ArrayList<>();
        list = ds1Mapper.selectOrderData();
        String filename = "./order.xlsx";
        EasyExcel.write(filename, OrderSuppDao.class).sheet("1").doWrite(list);
    }


    @Override
    public void queryData() {
        log.info("进入数据加载方法");
        dataList = ds1Mapper.selectDataTime();
    }

    /**
     * 同步初始时间
     */
    @Override
    public void syncTime() {
        ArrayList<UserDao> succList = new ArrayList<>();
        ArrayList<UserDao> errorList = new ArrayList<>();
        for (UserDao userDao : dataList) {
            String phoneNumber = userDao.getPhoneNumber();
            int i = ds2Mapper.selectUser(phoneNumber);
            if (i > 0) {
                succList.add(userDao);
            } else {
                errorList.add(userDao);
            }
        }
        ds2Mapper.batchUpdateUserTime(succList);
        log.info("错误数据 + ", errorList.toString());
        ArrayList<UserChargeDao> userChargeDaos = new ArrayList<>();
        for (UserDao userDao : errorList) {
            UserChargeDao userChargeDao = new UserChargeDao();
            userChargeDao.setPhonenumber(userDao.getPhoneNumber());
            userChargeDao.setUserName(userDao.getUserName());
            userChargeDaos.add(userChargeDao);
        }
        String filename = "./errorTime.xlsx";
        EasyExcel.write(filename, UserChargeDao.class).sheet("1").doWrite(userChargeDaos);
    }

    @Override
    public void selectUserFromNormal() {
        ArrayList<BatchImportUserNoAmountExcelVO> list = new ArrayList<>();
        int communityId = 135;
        list = ds2Mapper.selectUserFromNormal(communityId);
        String filename = "./batchImportUser.xlsx";
        EasyExcel.write(filename, BatchImportUserNoAmountExcelVO.class).sheet("1").doWrite(list);
    }


    @Override
    public void goldSyncData() {
        ArrayList<UserDao> userDaos = new ArrayList<>();
        int communityId = 135;
        userDaos = ds2Mapper.selectGoldUser(communityId);

        ArrayList<UserDao> succList = new ArrayList<>();
        ArrayList<UserDao> errorList = new ArrayList<>();
//        userDaos.parallelStream().forEach(userDao -> {
//            String phoneNumber = userDao.getPhoneNumber();
//            int i = ds2Mapper.selectUser(phoneNumber);
//            if (i > 0) {
//                succList.add(userDao);
//            } else {
//                errorList.add(userDao);
//            }
//        });
        for (UserDao userDao : userDaos) {
            String phoneNumber = userDao.getPhoneNumber();
            int i = ds2Mapper.selectUser(phoneNumber);
            if (i > 0) {
                succList.add(userDao);
            } else {
                errorList.add(userDao);
            }
        }
        ds2Mapper.batchUpdateUser(succList);
        log.info("错误数据大小{} ", errorList.size());
        log.info("错误数据 {}", errorList.toString());
        ArrayList<UserChargeDao> userChargeDaos = new ArrayList<>();
        for (UserDao userDao : errorList) {
            UserChargeDao userChargeDao = new UserChargeDao();
            userChargeDao.setPhonenumber(userDao.getPhoneNumber());
            userChargeDao.setUserName(userDao.getUserName());
            userChargeDaos.add(userChargeDao);
        }
        String filename = "./errorUser.xlsx";
        EasyExcel.write(filename, UserChargeDao.class).sheet("1").doWrite(userChargeDaos);
    }

    /**
     * 黄金集团同步订单扣款详情
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncOrderDetail() {
        int communityId = 3006;
        ArrayList<OrderDao> orderDaos = new ArrayList<>();
        orderDaos = ds3Mapper.selectOrder(communityId);
        ArrayList<OrderDedu> orderDedus = new ArrayList<>();
        for (OrderDao orderDao : orderDaos) {
            OrderDedu orderDedu = ds2Mapper.selectOrderDedu(orderDao.getOrderNo());
            if (ObjectUtil.isNotNull(orderDedu)) {
                orderDedus.add(orderDedu);
            }
        }
        log.info("数据大小{} ", orderDedus.size());
        ds3Mapper.batchInsertOrderDedu(orderDedus);
    }

    @Override
    public void syncUser() throws IOException {
        ArrayList<UserDao> userDao = ds2Mapper.selectGoldUser(1612);

        String postUrl = "https://back.zt31.cn/back/face-recognition-server/api/insertFaceFile";
        ArrayList<UserDao> errorList = new ArrayList<>();
        for (UserDao dao : userDao) {
            ArrayList<UserDao>succList = new ArrayList<>();
            String faceUrl = dao.getFaceUrl();
            String userName = dao.getUserName();
            // 构造URL
            URL url = new URL(faceUrl);
            // 打开连接
            URLConnection con = url.openConnection();
            // 输入流
            InputStream is = con.getInputStream();
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流
            //下载路径及下载图片名称
            String filename = "C:\\Users\\zhuqi\\Desktop\\log\\天津港人脸\\" + userName + ".jpg";
            File file = new File(filename);
            FileOutputStream os = new FileOutputStream(file, true);
            // 开始读取
            while ((len = is.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
            // 完毕，关闭所有链接
            os.close();
            is.close();
            Map<String, Object> resultRang = SignTools.getTreeMap();
            resultRang.put("groupId", "1612");
            resultRang.put("personId", dao.getZityId());
            resultRang.put("mobile", dao.getPhoneNumber());
            resultRang.put("name", dao.getUserName());
            String jsonDataStr = SymmetricEncoder.aesEncrypt("2B3DBD7DA1A154D8ACAB0A8F81817E7E", JSONUtil.toJsonStr(resultRang));
            resultRang.put("jsonDataStr", jsonDataStr);
            resultRang.put("appId", "149EB6EED81587B7");

            HttpResponse execute = HttpRequest.post(postUrl).form("jsonDataStr",jsonDataStr)
                    .form("appId", "149EB6EED81587B7")
                    .form("file", file)
                    .execute();
            String body = execute.body();
            log.info("响应{} ", body);

            if (StrUtil.isNotEmpty(body)) {
                JSONObject jsonObject = JSONUtil.parseObj(body);
                String code = jsonObject.getStr("code");
                if ("0000".equals(code) || "0011".equals(code)) {
                    dao.setFaceUrl(jsonObject.getJSONObject("data").getStr("faceUrl"));
                    succList.add(dao);
                    ds2Mapper.batchUpdateUser(succList);
                    log.info("修改成功");
                } else {
                    errorList.add(dao);
                }
            }
        }
        ArrayList<UserChargeDao> userChargeDaos = new ArrayList<>();
        for (UserDao d : errorList) {
            UserChargeDao userChargeDao = new UserChargeDao();
            userChargeDao.setPhonenumber(d.getPhoneNumber());
            userChargeDao.setUserName(d.getUserName());
            userChargeDaos.add(userChargeDao);
        }
        String filename = "./errorUser11.xlsx";
        EasyExcel.write(filename, UserChargeDao.class).sheet("1").doWrite(userChargeDaos);
    }


    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void updateMealData() {
        ids = ds2Mapper.selectIdFromTable();
        int size = 1000;
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(10
                , 10, 30, TimeUnit.SECONDS
                , new ArrayBlockingQueue<>(10));

        Semaphore semp = new Semaphore(10);
        // 数据分割
        List<List<Integer>> idSplitList = ListUtil.split(ids, size);

        for (List<Integer> idList : idSplitList) {
            // 根据分割后的 id 查询数据
            ArrayList<SmartCanteenMessageRecharge> dataList = ds2Mapper.selectMealData(idList);

            // 查询订单数据
            dataList.parallelStream().forEach((smartCanteenMessageRecharge) -> {
                SmartCanteenMessageRecharge orderData;
                orderData = ds2Mapper.selectOrderDate(smartCanteenMessageRecharge.getOrderNo());
                if (ObjectUtil.isEmpty(orderData)) {
                    orderData = ds2Mapper.selectOrderDateHistory(smartCanteenMessageRecharge.getOrderNo());
                }
                smartCanteenMessageRecharge.setAmount(orderData.getAmount());
                smartCanteenMessageRecharge.setStatus(orderData.getStatus());
                smartCanteenMessageRecharge.setCreateTime(orderData.getCreateTime());
            });


            List<List<SmartCanteenMessageRecharge>> splitDataList = ListUtil.split(dataList, 100);

            ArrayList<Future<Integer>> futureArrayList = new ArrayList<>();
            // 多线程数据处理
            for (int i = 0; i < splitDataList.size(); i++) {
                List<SmartCanteenMessageRecharge> smartCanteenMessageRecharges = splitDataList.get(i);
                // 批量插入数据
                Future<Integer> submit = poolExecutor.submit(() -> {

                    String name = Thread.currentThread().getName();
                    int count = 0;
                    try {
                        semp.acquire();
                        count = ds2Mapper.batchUpdateMealRecharges(smartCanteenMessageRecharges);
                    } catch (Exception e) {
                        log.info("线程：执行异常，输出当前数据", name, count);
                        String filename = "./" + name + DateUtil.now() + ".xlsx";
                        EasyExcel.write(filename, BatchImportUserNoAmountExcelVO.class).sheet("1")
                                .doWrite(smartCanteenMessageRecharges);
                        e.printStackTrace();
                        log.error(e.getMessage());
                    }
                    log.info("线程：{} 执行完成，受影响行数：{}", name, count);
                    semp.release();
                    return count;
                });
                futureArrayList.add(submit);
            }

            // 检查所以线程是否都执行完成
            while (true) {
                int queueLength = semp.availablePermits();
                if (queueLength == 10) {
                    log.info("所有线程全部执行完成，进行下一轮循环");
                    break;
                }
            }
        }
        log.info("任务完成");



        poolExecutor.shutdown();
    }


    /**
     * 测试 DS3数据库
     */
    @Override
    public void testDs3() {
        log.info(ds3Mapper.toString());
        int i = ds3Mapper.selectUser("17625006600");

    }

    @Override
    public void selectUserImage() {
        ArrayList<UserDao> userDao = ds2Mapper.selectNoAuthUser(1612);
        for (UserDao dao : userDao) {
            String faceUrl = dao.getFaceUrl();
            String userName = dao.getZityId();
            try {
                // 构造URL
                URL url = new URL(faceUrl);
                // 打开连接
                URLConnection con = url.openConnection();
                // 输入流
                InputStream is = con.getInputStream();
                // 1K的数据缓冲
                byte[] bs = new byte[1024];
                // 读取到的数据长度
                int len;
                // 输出的文件流
                //下载路径及下载图片名称
                String filename = "C:\\Users\\zhuqi\\Desktop\\log\\天津港人脸2\\" + userName + ".jpg";
                File file = new File(filename);
                FileOutputStream os = new FileOutputStream(file, true);
                // 开始读取
                while ((len = is.read(bs)) != -1) {
                    os.write(bs, 0, len);
                }
                // 完毕，关闭所有链接
                os.close();
                is.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void updateUser() {
        ArrayList<UserDao> userDao = ds2Mapper.selectNoAuthUser(1612);
        ds2Mapper.batchUpdateUser(userDao);

    }
}
